// Copyright 2007-2009 Stuart Caborn, Alex Scordellis
//  
//  Licensed under the Apache License, Version 2.0 (the "License"); you may not
//  use this file except in compliance with the License. You may obtain a copy of
//  the License at
//  
//  http://www.apache.org/licenses/LICENSE-2.0
//  
//  Unless required by applicable law or agreed to in writing, software
//  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
//  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
//  License for the specific language governing permissions and limitations under
//  the License.
// 


using System;
using System.Linq;
using NUnit.Framework;
using NUnit.Framework.SyntaxHelpers;

namespace NSynthesis.Test.Reflection
{
    [TestFixture]
    public class ReflectionGotchas
    {
        [Test]
        public void base_type_of_a_generic_type_definition_is_not_a_generic_type_definition()
        {
            Assert.That(typeof (GenericOverride<>).IsGenericTypeDefinition);

            Assert.That(typeof (GenericOverride<>).BaseType.IsGenericTypeDefinition, Is.False);

            Assert.That(typeof (GenericClass<>) == typeof (GenericOverride<>).BaseType, Is.False);

            Assert.That(typeof (GenericClass<>) == typeof (GenericOverride<>).BaseType.GetGenericTypeDefinition(), Is.True);

            Assert.That(typeof (GenericClass<>).IsGenericTypeDefinition);
        }

        [Test]
        public void parent_interfaces_of_a_generic_type_definition_are_not_generic_type_definitions()
        {
            Assert.That(typeof (GenericClass<>).IsGenericTypeDefinition);

            Assert.That(typeof (GenericClass<>).GetInterfaces().First().IsGenericTypeDefinition, Is.False);

            Assert.That(typeof (IInterface<>) == typeof (GenericClass<>).GetInterfaces().First(), Is.False);

            Assert.That(typeof (IInterface<>) == typeof (GenericClass<>).GetInterfaces().First().GetGenericTypeDefinition(), Is.True);

            Assert.That(typeof (IInterface<>).IsGenericTypeDefinition);
        }

        [Test]
        public void methods_on_a_generic_class_that_do_not_involve_the_generic_params_still_ContainGenericParameters()
        {
            var method = typeof (GenericClass<>).GetMethod("DoesntUseT");
            Assert.That(method.ContainsGenericParameters,
                        "The method still ContainsGenericParameters");
            Assert.That(method.GetParameters().All(info => !info.ParameterType.IsGenericParameter),
                        "So to tell that they aren't involved in the signature you have to check that none of the method args are generic parameters.");
            // Really this makes sense - it's still legal to use T in the body of such a method
        }

        private interface IInterface<T>
        {
        }

        private class GenericClass<T> : IInterface<T>
        {
            public void DoesntUseT(int x, string y, Type notT)
            {
            }
        }

        private class GenericOverride<T> : GenericClass<T>
        {
        }
    }
}